<?php
class Wow_Armory_Config
{
    
    /**
     * Contains the short handle for europe.
     * 
     * @var string
     */
    const EU = 'eu';
    
    /**
     * Contains the short handle for the usa.
     * 
     * @var string
     */
    const US = 'us';
    
    /**
     * Contains the short handle for korea.
     * 
     * @var string
     */
    const KR = 'kr';
    
    /**
     * Contains the short handle for china.
     * 
     * @var string
     */
    const CN = 'cn';
    
    /**
     * Contains the short handle for taiwan.
     * 
     * @var string
     */
    const TW = 'tw';
    
    /**
     * Cotains the configuration as a array.
     * 
     * @var array
     */
    protected $_config = array();
    
    /**
     * Creates the object. 
     * 
     * If init is true a basic configuration will be loaded. Attention: This
     * configuration can be overwrited by user.
     * 
     * @param  boolean $init
     * @return void
     */
    public function __construct($init = false)
    {
        if ($init) {
            $this->setArmoryUrl('http://%s.wowarmory.com')
                 ->setCharacterSheet('character-sheet.xml')
                 ->setGuildSheet('guild-info.xml')
                 ->setTalentSheet('character-talents.xml')
                 ->setReputationSheet('character-reputation.xml')
                 ->setAchievementSheet('character-achievements.xml')
                 ->setStatisticSheet('character-statistics.xml')
                 ->setRealmGetter('r')
                 ->setCharacterNameGetter('cn')
                 ->setGuildNameGetter('gn');
        }
    }
    
    /**
     * MM: Checks the existing status of the given value.
     * 
     * @param   string $var
     * @return  boolean
     */
    public function __isset($var)
    {
        return isset($this->_config[$var]);
    }
    
    /**
     * MM: Returns the given value as a mixed param.
     * 
     * @param  string $name
     * @return mixed|null 
     */
    public function __get($name)
    {
        if ($this->__isset($name)) {
            return $this->_config[$name];
        }
        
        return null;
    }
    
    /**
     * MM: Sets a new value by name and returns him self.
     * 
     * @param  string $name
     * @param  mixed $value
     * @return Wow_Armory_Config
     */
    public function __set($name, $value)
    {
        $this->_config[$name] = $value;
    }
    
    /**
     * Sets a new value by name and returns him self.
     * 
     * @see    Wow_Armory_Config->__set($name, $value).
     * @param  string $name
     * @param  string $value
     * @return Wow_Armory_Config
     */
    public function setConfig($name, $value)
    {
        $this->__set($name, $value);
        return $this;
    }
    
    /**
     * Gets a commited configuration as a mixed value by name as string.
     * 
     * @param  string $name
     * @return mixed|null
     */
    public function getConfig($name)
    {
        //FIXME: NULL!?!?!?!??!
        return $this->__get($name);
    }
    
    /**
     * Parse a complete ArrayObject to the configuration in Wow_Armory_Configuration.
     * After finish he returns him self.
     * 
     * @param  ArrayObject $config
     * @return Wow_Armory_Config
     */
    public function parseConfiguration(ArrayObject $config)
    {
        $this->_config = $config->getArrayCopy();
        return $this;
    }
    
    /**
     * Sets the character.
     * 
     * @param  Wow_Armory_Character $value
     * @return Wow_Armory_Config
     */
    public function setCharacter(Wow_Armory_Character $value)
    {
        return $this->setConfig('character', $value);
    }

    /**
     * Sets the guild.
     * 
     * @param Wow_Armory_Guild $value
     * @return Wow_Armory_Config
     */
    public function setGuild(Wow_Armory_Guild $value)
    {
        return $this->setConfig('guild', $value);
    }
    
    /**
     * Sets the realm.
     * 
     * @param Wow_Armory_Realm $value
     * @return Wow_Armory_Config
     */
    public function setRealm(Wow_Armory_Realm $value)
    {
        return $this->setConfig('realm', $value);
    }
    
    /**
     * Sets the armory url as a string with a placeholder for the location.
     * 
     * @uses   sprintf
     * @param  string $url
     * @return Wow_Armory_Config
     */
    public function setArmoryUrl($url)
    {
        if (!is_string($url)) {
            throw new Wow_Armory_Exception('', 1000);
        }
        
        return $this->setConfig('armoryUrl', $url);
    }
    
    /**
     * Sets the location as a string. Use the class constants of Wow_Armory_Config.
     * 
     * @param  string $location
     * @return Wow_Armory_Config
     */
    public function setLocation($location = Wow_Armory_Config::EU)
    {
        if (!is_string($location)) {
            throw new Wow_Armory_Exception('', 1001);
        }
        
        return $this->setConfig('location', $location);
    }
    
    /**
     * Sets the realm getter as a string.
     * 
     * @param  string $getter
     * @return Wow_Armory_Config
     */
    public function setRealmGetter($getter)
    {
        if (!is_string($getter)) {
            throw new Wow_Armory_Exception('', 1002);
        }
        
        return $this->setConfig('realmGetter', $getter);
    }
    
    /**
     * Sets the character getter as a string.
     * 
     * @param  string $getter
     * @return Wow_Armory_Config
     */
    public function setCharacterNameGetter($getter)
    {
        if (!is_string($getter)) {
            throw new Wow_Armory_Exception('', 1003);
        }
        
        return $this->setConfig('characterNameGetter', $getter);
    }
    
    /**
     * Sets the guild name getter as a string.
     * 
     * @param  string $getter
     * @return Wow_Armory_Config
     */
    public function setGuildNameGetter($getter)
    {
        if (!is_string($getter)) {
            throw new Wow_Armory_Exception('', 1004);
        }
        
        return $this->setConfig('guildNameGetter', $getter);
    }
    
    /**
     * Sets the character sheet as a string.
     * 
     * @param  string $sheet
     * @return Wow_Armory_Config
     */
    public function setCharacterSheet($sheet)
    {
        if (!is_string($sheet)) {
            throw new Wow_Armory_Exception('', 1005);
        }
        
        return $this->setConfig('characterSheet', $sheet);
    }
    
    /**
     * Sets the guild sheet as a string.
     * 
     * @param  string $sheet
     * @return Wow_Armory_Config
     */
    public function setGuildSheet($sheet)
    {
        if (!is_string($sheet)) {
            throw new Wow_Armory_Exception('', 1006);
        }
        
        return $this->setConfig('guildSheet', $sheet);
    }
    
    /**
     * Sets the talent sheet as a string.
     * 
     * @param  string $sheet
     * @return Wow_Armory_Config
     */
    public function setTalentSheet($sheet)
    {
        if (!is_string($sheet)) {
            throw new Wow_Armory_Exception('', 1007);
        }
        
        return $this->setConfig('talentSheet', $sheet);
    }
    
    /**
     * Sets the reputation sheet as a string.
     * 
     * @param  string $sheet
     * @return Wow_Armory_Config
     */
    public function setReputationSheet($sheet)
    {
        if (!is_string($sheet)) {
            throw new Wow_Armory_Exception('', 1008);
        }
        
        return $this->setConfig('reputationSheet', $sheet);
    }
    
    /**
     * Sets the achievement sheet as a string.
     * 
     * @param  string $sheet
     * @return Wow_Armory_Config
     */
    public function setAchievementSheet($sheet)
    {
        if (!is_string($sheet)) {
            throw new Wow_Armory_Exception('', 1009);
        }
        
        return $this->setConfig('achievementSheet', $sheet);
    }
    
    /**
     * Sets the statistic sheet as a string.
     * 
     * @param  string $sheet
     * @return Wow_Armory_Config
     */
    public function setStatisticSheet($sheet)
    {
        if (!is_string($sheet)) {
            throw new Wow_Armory_Exception('', 1010);
        }
        
        return $this->setConfig('statisticSheet', $sheet);
    }
    
    /**
     * Sets the cache status.
     * 
     * @param  boolean $value
     * @return Wow_Armory_Config
     */
    public function setCache($value)
    {
        if (!is_bool($value)) {
            throw new Wow_Armory_Exception('', 1011);
        }
        
        return $this->setConfig('cache', $value);
    }
    
    /**
     * Sets a cache handler class.
     * 
     * @param  Wow_Armory_Cache_Abstract $cache
     * @return Wow_Armory_Config
     */
    public function setCacheHandler(Wow_Armory_Cache_Abstract $cache)
    {
        return $this->setConfig('cacheHandler', $cache);
    }
    
    /**
     * Gets the character.
     * 
     * @return Wow_Armory_Character
     */
    public function getCharacter()
    {
        return $this->getConfig('character');
    }
    
    /**
     * Gets the guild.
     * 
     * @return Wow_Armory_Guild
     */
    public function getGuild()
    {
        return $this->getConfig('guild');
    }
    
    /**
     * Gets the realm.
     * 
     * @return Wow_Armory_Realm
     */
    public function getRealm()
    {
        return $this->getConfig('realm');
    }
    
    /**
     * Gets the armory url as a string
     * 
     * @return string
     */
    public function getArmoryUrl()
    {
        return $this->getConfig('armoryUrl');
    }
    
    /**
     * Gets the location as a string.
     * 
     * @return string
     */
    public function getLocation()
    {
        return $this->getConfig('location');
    }
    
    /**
     * Gets the realm getter.
     * 
     * @return string
     */
    public function getRealmGetter()
    {
        return $this->getConfig('realmGetter');
    }
    
    /**
     * Gets the character name getter.
     * 
     * @return string
     */
    public function getCharacterNameGetter()
    {
        return $this->getConfig('characterNameGetter');
    }
    
    /**
     * Gets the guild name getter.
     * 
     * @return string
     */
    public function getGuildNameGetter()
    {       
        return $this->getConfig('guildNameGetter');
    }
    
    /**
     * Gets the character sheet.
     * 
     * @return string
     */
    public function getCharacterSheet()
    {
        return $this->getConfig('characterSheet');
    }
    
    /**
     * Gets the guild sheet.
     * 
     * @return string
     */
    public function getGuildSheet()
    {
        return $this->getConfig('guildSheet');
    }
    
    /**
     * Gets the talent sheet.
     * 
     * @return string
     */
    public function getTalentSheet()
    {
        return $this->getConfig('talentSheet');
    }
    
    /**
     * Gets the reputation sheet.
     * 
     * @return string
     */
    public function getReputationSheet()
    {
        return $this->getConfig('reputationSheet');
    }
    
    /**
     * Gets the achievement sheet.
     * 
     * @return string
     */
    public function getAchievementSheet()
    {
        return $this->getConfig('achievementSheet');
    }
    
    /**
     * Gets the statistics sheet.
     * 
     * @return string
     */
    public function getStatisticSheet()
    {
        return $this->getConfig('statisticSheet');
    }
    
    /**
     * Gets the cache status.
     * 
     * @return boolean
     */
    public function getCache()
    {
        return $this->getConfig('cache');
    }
    
    /**
     * Gets the cache handler.
     * 
     * @return Wow_Armory_Cache_Abstract
     */
    public function getCacheHandler()
    {
        return $this->getConfig('cacheHandler');
    }
    
    /**
     * Returns the configuration as array.
     * 
     * @return array
     */
    public function toArray()
    {
        return $this->_config;
    }
    
    /**
     * Returns the configuration as array object.
     * 
     * @return ArrayObject
     */
    public function getArrayObject()
    {
        return new ArrayObject($this->_config);
    }
    
    /**
     * Checks the validation of all given values.
     * 
     * @return boolean
     */
    public function isValid()
    {
        // FIXME: Implement this method.
        return true;
    }
    
}